//
// RS Game Framework
// Copyright © 2009 Jedd Haberstro
// jhaberstro@gmail.com
// 
// $Id:
//

#ifndef RS_REFLECTION_CONSTRUCTOR_HPP
#define RS_REFLECTION_CONSTRUCTOR_HPP

#include "rs/reflection/Types.hpp"
#include "rs/AnyFxnPointer.hpp"
#include "rs/Assert.hpp"

namespace rs
{
    namespace reflection
    {
        
        namespace internal
        {
            class ConstructorFactory;
        }
        
        class Constructor
        {
            friend class internal::ConstructorFactory;
            
        public:
            
            typedef std::vector< UInt64 > ArgumentTypesContainer;

        public:
            
            Constructor();

            void* operator()() const;

            void operator()(void* obj) const;

            template< typename TArg1 >
            void* operator()(TArg1 arg1) const;

            template< typename TArg1 >
            void operator()(void* obj, TArg1 arg1) const;

            template< typename TArg1, typename TArg2 >
            void* operator()(TArg1 arg1, TArg2 arg2) const;

            template< typename TArg1, typename TArg2 >
            void operator()(void* obj, TArg1 arg1, TArg2 arg2) const;

            template< typename TArg1, typename TArg2, typename TArg3 >
            void* operator()(TArg1 arg1, TArg2 arg2, TArg3 arg3) const;

            template< typename TArg1, typename TArg2, typename TArg3 >
            void operator()(void* obj, TArg1 arg1, TArg2 arg2, TArg3 arg3) const;

            template< typename TArg1, typename TArg2, typename TArg3, typename TArg4 >
            void* operator()(TArg1 arg1, TArg2 arg2, TArg3 arg3, TArg4 arg4) const;

            template< typename TArg1, typename TArg2, typename TArg3, typename TArg4 >
            void operator()(void* obj, TArg1 arg1, TArg2 arg2, TArg3 arg3, TArg4 arg4) const;

            template< typename TArg1, typename TArg2, typename TArg3, typename TArg4, typename TArg5 >
            void* operator()(TArg1 arg1, TArg2 arg2, TArg3 arg3, TArg4 arg4, TArg5 arg5) const;

            template< typename TArg1, typename TArg2, typename TArg3, typename TArg4, typename TArg5 >
            void operator()(void* obj, TArg1 arg1, TArg2 arg2, TArg3 arg3, TArg4 arg4, TArg5 arg5) const;
            
            Type GetArgumentType(UInt32 i) const;
            
            UInt64 GetRawArgumentType(UInt32 i) const;
            RsSize GetArgumentCount() const;

        protected:

            template< typename TCreatorFunc >
            Constructor(TCreatorFunc func, ArgumentTypesContainer const& argumentTypes, RsSize size);
            
            template< typename TCreatorFunc >
            Constructor(TCreatorFunc func, RsSize size);

        private:

            ArgumentTypesContainer argumentTypes_; 
            rs::internal::any_fxn_pointer creatorFunc_;
            RsSize classSize_;
        };
    }
}

#define RS_REFLECTION_CONSTRUCTOR_IMPLEMENTATION_GUARD
#include "rs/reflection/Constructor.ipp"
#undef RS_REFLECTION_CONSTRUCTOR_IMPLEMENTATION_GUARD

#endif // RS_REFLECTION_CONSTRUCTOR_HPP